﻿using NDF.ComponentModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace System.Linq
{
    /// <summary>
    /// 为常见的快速操作 <see cref="System.Collections.Generic.IEnumerable(T)"/> 泛型序列对象操作提供实用工具方法。
    /// </summary>
    public static partial class EnumerableHelper
    {
        /// <summary>
        /// 基于谓词确定序列中的所有元素是否满足条件。将在谓词函数的逻辑中使用每个元素的索引。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <param name="source">一个 <see cref="System.Collections.Generic.IEnumerable(TSource)"/>，其元素将应用谓词。</param>
        /// <param name="predicate">用于测试每个源元素是否满足条件的函数；该函数的第二个参数表示源元素的索引。</param>
        /// <returns>如果源序列中的每个元素都通过指定谓词中的测试，或者序列为空，则为 true；否则为 false。</returns>
        public static bool All<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
        {
            var array = source.ToArray();
            for (var i = 0; i < array.Length; i++)
            {
                if (!predicate.Invoke(array[i], i))
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 基于谓词确定序列中的任何元素是否都满足条件。 将在谓词函数的逻辑中使用每个元素的索引。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <param name="source">一个 <see cref="System.Collections.Generic.IEnumerable(TSource)"/>，其元素将应用谓词。</param>
        /// <param name="predicate">用于测试每个源元素是否满足条件的函数；该函数的第二个参数表示源元素的索引。</param>
        /// <returns>如果源序列中的任意一元素通过指定谓词中的测试，则为 true；否则为 false。</returns>
        public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
        {
            var array = source.ToArray();
            for (var i = 0; i < array.Length; i++)
            {
                if (predicate.Invoke(array[i], i))
                {
                    return true;
                }
            }
            return false;
        }



        /// <summary>
        /// 返回序列中指定索引处的元素。
        /// 同 <see cref="System.Linq.Enumerable.ElementAt(TSource, Int32)"/> 方法。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <param name="source">要从中返回元素的 <see cref="System.Collections.Generic.IEnumerable(TSource)"/>。</param>
        /// <param name="index">要检索的从零开始的元素索引。</param>
        /// <returns>源序列中指定位置处的元素。</returns>
        public static TSource Get<TSource>(this IEnumerable<TSource> source, int index)
        {
            return source.ElementAt(index);
        }

        /// <summary>
        /// 返回序列中指定索引处的元素；如果索引超出范围，则返回默认值。
        /// 同 <see cref="System.Linq.Enumerable.ElementAtOrDefault(TSource, Int32)"/> 方法。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <param name="source">要从中返回元素的 <see cref="System.Collections.Generic.IEnumerable(TSource)"/>。</param>
        /// <param name="index">要检索的从零开始的元素索引。</param>
        /// <returns>如果索引超出源序列的范围，则为 default(TSource)；否则为源序列中指定位置处的元素。</returns>
        public static TSource GetOrDefault<TSource>(this IEnumerable<TSource> source, int index)
        {
            return source.ElementAtOrDefault(index);
        }



        public static int IndexOf<TSource>(this IEnumerable<TSource> source, TSource value)
        {
            return source.ToList().IndexOf(value);
        }

        public static int IndexOf<TSource>(this IEnumerable<TSource> source, TSource value, int startIndex)
        {
            return source.ToList().IndexOf(value, startIndex);
        }

        public static int IndexOf<TSource>(this IEnumerable<TSource> source, TSource value, int startIndex, int count)
        {
            return source.ToList().IndexOf(value, startIndex, count);
        }


        public static int IndexOf<TSource>(this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
        {
            List<TSource> array = source.ToList();
            for (int i = 0; i < array.Count; i++)
            {
                if (comparer.Equals(value, array[i]))
                {
                    return i;
                }
            }
            return -1;
        }

        public static int IndexOf<TSource>(this IEnumerable<TSource> source, TSource value, int startIndex, IEqualityComparer<TSource> comparer)
        {
            List<TSource> array = source.ToList(),
                          range = array.GetRange(startIndex, array.Count - startIndex);
            for (int i = 0; i < range.Count; i++)
            {
                if (comparer.Equals(value, range[i]))
                {
                    return startIndex + i;
                }
            }
            return -1;
        }

        public static int IndexOf<TSource>(this IEnumerable<TSource> source, TSource value, int startIndex, int count, IEqualityComparer<TSource> comparer)
        {
            List<TSource> array = source.ToList(),
                          range = array.GetRange(startIndex, count);
            for (int i = 0; i < range.Count; i++)
            {
                if (comparer.Equals(value, range[i]))
                {
                    return startIndex + i;
                }
            }
            return -1;
        }





        public static int LastIndexOf<TSource>(this IEnumerable<TSource> source, TSource value)
        {
            return source.ToList().LastIndexOf(value);
        }

        public static int LastIndexOf<TSource>(this IEnumerable<TSource> source, TSource value, int startIndex)
        {
            return source.ToList().LastIndexOf(value, startIndex);
        }

        public static int LastIndexOf<TSource>(this IEnumerable<TSource> source, TSource value, int startIndex, int count)
        {
            return source.ToList().LastIndexOf(value, startIndex, count);
        }


        public static int LastIndexOf<TSource>(this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
        {
            List<TSource> array = source.ToList();
            for (int i = array.Count - 1; i >= 0; i--)
            {
                if (comparer.Equals(value, array[i]))
                {
                    return i;
                }
            }
            return -1;
        }

        public static int LastIndexOf<TSource>(this IEnumerable<TSource> source, TSource value, int startIndex, IEqualityComparer<TSource> comparer)
        {
            List<TSource> array = source.ToList(),
                          range = array.GetRange(startIndex, array.Count - startIndex);
            for (int i = range.Count - 1; i >= 0; i--)
            {
                if (comparer.Equals(value, range[i]))
                {
                    return startIndex + i;
                }
            }
            return -1;
        }

        public static int LastIndexOf<TSource>(this IEnumerable<TSource> source, TSource value, int startIndex, int count, IEqualityComparer<TSource> comparer)
        {
            List<TSource> array = source.ToList(),
                          range = array.GetRange(startIndex, count);
            for (int i = range.Count - 1; i >= 0; i--)
            {
                if (comparer.Equals(value, range[i]))
                {
                    return startIndex + i;
                }
            }
            return -1;
        }




        /// <summary>
        /// 返回一个序列 <see cref="System.Collections.Generic.IEnumerable(Of T)"/> ，它是源序列中的一个子集。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素类型。</typeparam>
        /// <param name="source">源序列对象。</param>
        /// <param name="startIndex">返回剩余元素前要跳过的元素数量，也可理解为范围开始处的从零开始的 <see cref="System.Collections.Generic.IEnumerable(Of T)"/> 索引。</param>
        /// <returns><see cref="System.Collections.Generic.IEnumerable(Of T)"/>，它表示源 <see cref="System.Collections.Generic.IEnumerable(Of T)"/> 中元素的子集。</returns>
        public static IEnumerable<TSource> GetRange<TSource>(this IEnumerable<TSource> source, int startIndex)
        {
            return source.Skip(startIndex);
        }

        /// <summary>
        /// 返回一个序列 <see cref="System.Collections.Generic.IEnumerable(Of T)"/> ，它是源序列中的一个子集。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素类型。</typeparam>
        /// <param name="source">源序列对象。</param>
        /// <param name="startIndex">返回剩余元素前要跳过的元素数量，也可理解为范围开始处的从零开始的 <see cref="System.Collections.Generic.IEnumerable(Of T)"/> 索引。</param>
        /// <param name="count">范围中的元素数，同时也表示要返回的元素数量。</param>
        /// <returns><see cref="System.Collections.Generic.IEnumerable(Of T)"/>，它表示源 <see cref="System.Collections.Generic.IEnumerable(Of T)"/> 中元素的子集。</returns>
        public static IEnumerable<TSource> GetRange<TSource>(this IEnumerable<TSource> source, int startIndex, int count)
        {
            return source.Skip(startIndex).Take(count);
        }






        /// <summary>
        /// 以 <seealso cref="DataPager.DefaultPageSize"/> 值指示的默认页面尺寸大小获取泛型序列中的第一页(pageIndex 为 0)分页数据。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <param name="source">一个 System.Collections.Generic.IEnumerable(T)，用于从中返回分页元素。</param>
        /// <returns>
        /// 返回一个 <see cref="System.Collections.Generic.IEnumerable(TSource)"/>，返回的序列为源序列 source 的子集，其表示 source 第 1 页(pageIndex 为 0)的
        /// 数据，返回序列中元素数量为 <seealso cref="DataPager.DefaultPageSize"/>(如果是返回的是最后一页数据，其数量可能不足 <seealso cref="DataPager.DefaultPageSize"/>)。
        /// </returns>
        public static IEnumerable<TSource> SplitPage<TSource>(this IEnumerable<TSource> source)
        {
            return SplitPage(source, 0, DataPager.DefaultPageSize);
        }

        /// <summary>
        /// 以指定的页面索引号、<seealso cref="DataPager.DefaultPageSize"/> 值指示的默认页面尺寸大小获取泛型序列中的分页数据。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <param name="source">一个 System.Collections.Generic.IEnumerable(T)，用于从中返回分页元素。</param>
        /// <param name="pageIndex">返回数据页所在源序列中的页面索引号，从 0 开始计数。</param>
        /// <returns>
        /// 返回一个 <see cref="System.Collections.Generic.IEnumerable(TSource)"/>，返回的序列为源序列 source 的子集，其表示 source 第 pageIndex(从 0 开始计数) 页的
        /// 数据，返回序列中元素数量为 <seealso cref="DataPager.DefaultPageSize"/>(如果是返回的是最后一页数据，其数量可能不足 <seealso cref="DataPager.DefaultPageSize"/>)。
        /// </returns>
        public static IEnumerable<TSource> SplitPage<TSource>(this IEnumerable<TSource> source, int pageIndex)
        {
            return SplitPage(source, pageIndex);
        }

        /// <summary>
        /// 以指定的页面索引号、页面尺寸大小获取泛型序列中的分页数据。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <param name="source">一个 System.Collections.Generic.IEnumerable(T)，用于从中返回分页元素。</param>
        /// <param name="pageIndex">返回数据页所在源序列中的页面索引号，从 0 开始计数。</param>
        /// <param name="pageSize">返回数据页的页面尺寸，即一页有多少行数据。</param>
        /// <returns>
        /// 返回一个 <see cref="System.Collections.Generic.IEnumerable(TSource)"/>，返回的序列为源序列 source 的子集，其表示 source 第 pageIndex(从 0 开始计数) 页的
        /// 数据，返回序列中元素数量为 pageSize(如果是返回的是最后一页数据，其数量可能不足 pageSize)。
        /// </returns>
        public static IEnumerable<TSource> SplitPage<TSource>(this IEnumerable<TSource> source, int pageIndex, int pageSize)
        {
            return source.GetRange(pageIndex * pageSize, pageSize);
        }


        /// <summary>
        /// 以 <seealso cref="DataPager.DefaultPageSize"/> 值指示的默认页面尺寸大小和数据排序方式获取泛型序列中的第一页(pageIndex 为 0)分页数据。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <param name="source">一个 System.Collections.Generic.IEnumerable(T)，用于从中返回分页元素。</param>
        /// <param name="sorter">用于排序比较元素时要使用的 <see cref="System.Comparison(TSource)"/>。</param>
        /// <returns>
        /// 返回一个 <see cref="System.Collections.Generic.IEnumerable(TSource)"/>，返回的序列为源序列 source 的子集，其表示 source 第 1 页(pageIndex 为 0)的
        /// 数据，返回序列中元素数量为 <seealso cref="DataPager.DefaultPageSize"/>(如果是返回的是最后一页数据，其数量可能不足 <seealso cref="DataPager.DefaultPageSize"/>)。
        /// </returns>
        public static IEnumerable<TSource> SplitPage<TSource>(this IEnumerable<TSource> source, Comparison<TSource> sorter)
        {
            return SplitPage(source, 0, sorter);
        }

        /// <summary>
        /// 以指定的页面索引号、<seealso cref="DataPager.DefaultPageSize"/> 值指示的默认页面尺寸大小和数据排序方式获取泛型序列中的分页数据。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <param name="source">一个 System.Collections.Generic.IEnumerable(T)，用于从中返回分页元素。</param>
        /// <param name="pageIndex">返回数据页所在源序列中的页面索引号，从 0 开始计数。</param>
        /// <param name="sorter">用于排序比较元素时要使用的 <see cref="System.Comparison(TSource)"/>。</param>
        /// <returns>
        /// 返回一个 <see cref="System.Collections.Generic.IEnumerable(TSource)"/>，返回的序列为源序列 source 的子集，其表示 source 第 pageIndex(从 0 开始计数) 页的
        /// 数据，返回序列中元素数量为 <seealso cref="DataPager.DefaultPageSize"/>(如果是返回的是最后一页数据，其数量可能不足 <seealso cref="DataPager.DefaultPageSize"/>)。
        /// </returns>
        public static IEnumerable<TSource> SplitPage<TSource>(this IEnumerable<TSource> source, int pageIndex, Comparison<TSource> sorter)
        {
            return SplitPage(source, pageIndex, DataPager.DefaultPageSize, sorter);
        }

        /// <summary>
        /// 以指定的页面索引号、页面尺寸大小和数据排序方式获取泛型序列中的分页数据。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <param name="source">一个 System.Collections.Generic.IEnumerable(T)，用于从中返回分页元素。</param>
        /// <param name="pageIndex">返回数据页所在源序列中的页面索引号，从 0 开始计数。</param>
        /// <param name="pageSize">返回数据页的页面尺寸，即一页有多少行数据。</param>
        /// <param name="sorter">用于排序比较元素时要使用的 <see cref="System.Comparison(TSource)"/>。</param>
        /// <returns>
        /// 返回一个 <see cref="System.Collections.Generic.IEnumerable(TSource)"/>，返回的序列为源序列 source 的子集，其表示 source 第 pageIndex(从 0 开始计数) 页的
        /// 数据，返回序列中元素数量为 pageSize(如果是返回的是最后一页数据，其数量可能不足 pageSize)。
        /// </returns>
        public static IEnumerable<TSource> SplitPage<TSource>(this IEnumerable<TSource> source, int pageIndex, int pageSize, Comparison<TSource> sorter)
        {
            return source.Sort(sorter).GetRange(pageIndex * pageSize, pageSize);
        }



        /// <summary>
        /// 以 <seealso cref="DataPager.DefaultPageSize"/> 值指示的默认页面尺寸大小对序列进行分页处理并返回分页后第一页(pageIndex 为 0)数据所构成的分页结果。
        /// </summary>
        /// <typeparam name="TSource"source 中的元素的类型。>source 中的元素的类型。</typeparam>
        /// <param name="source">一个 System.Collections.Generic.IEnumerable<T>，用于进行分页处理。</param>
        /// <returns>
        /// 返回一个 <see cref="NDF.ComponentModel.PagingData(TSource)"/>：
        /// 其 Data 属性表示的页面数据内容为源序列 source 的子集，其 PageSize 属性为 <seealso cref="DataPager.DefaultPageSize"/> 属性值，
        /// 其 PageIndex 属性为 0(表示第一页)，其 RowCount 属性为源序列 source 的总元素数量。
        /// </returns>
        public static PagingData<TSource> ToPagingData<TSource>(this IEnumerable<TSource> source)
        {
            return ToPagingData(source, 0);
        }

        /// <summary>
        /// 以指定的页面索引号、<seealso cref="DataPager.DefaultPageSize"/> 值指示的默认页面尺寸大小对序列进行分页处理并返回分页后的结果。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <param name="source">一个 System.Collections.Generic.IEnumerable<T>，用于进行分页处理。</param>
        /// <param name="pageIndex">返回数据页所在源序列中的页面索引号，从 0 开始计数。</param>
        /// <returns>
        /// 返回一个 <see cref="NDF.ComponentModel.PagingData(TSource)"/>：
        /// 其 Data 属性表示的页面数据内容为源序列 source 的子集，其 PageSize 属性为 <seealso cref="DataPager.DefaultPageSize"/> 属性值，
        /// 其 PageIndex 属性为传入的参数 pageIndex，其 RowCount 属性为源序列 source 的总元素数量。
        /// </returns>
        public static PagingData<TSource> ToPagingData<TSource>(this IEnumerable<TSource> source, int pageIndex)
        {
            return ToPagingData(source, pageIndex, DataPager.DefaultPageSize);
        }

        /// <summary>
        /// 以指定的页面索引号、页面尺寸大小对序列进行分页处理并返回分页后的结果。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <param name="source">一个 System.Collections.Generic.IEnumerable<T>，用于进行分页处理。</param>
        /// <param name="pageIndex">返回数据页所在源序列中的页面索引号，从 0 开始计数。</param>
        /// <param name="pageSize">返回数据页的页面尺寸，即一页有多少行数据。</param>
        /// <returns>
        /// 返回一个 <see cref="NDF.ComponentModel.PagingData(TSource)"/>：
        /// 其 Data 属性表示的页面数据内容为源序列 source 的子集，其 PageSize 属性为传入的参数 pageSize，
        /// 其 PageIndex 属性为传入的参数 pageIndex，其 RowCount 属性为源序列 source 的总元素数量。
        /// </returns>
        public static PagingData<TSource> ToPagingData<TSource>(this IEnumerable<TSource> source, int pageIndex, int pageSize)
        {
            return new PagingData<TSource>(pageIndex, pageSize, source.Count(), source.SplitPage(pageIndex, pageSize));
        }


        /// <summary>
        /// 以 <seealso cref="DataPager.DefaultPageSize"/> 值指示的默认页面尺寸大小和数据排序方式对序列进行分页处理并返回分页后第一页(pageIndex 为 0)数据所构成的分页结果。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <param name="source">一个 System.Collections.Generic.IEnumerable<T>，用于进行分页处理。</param>
        /// <param name="sorter">用于排序比较元素时要使用的 <see cref="System.Comparison(TSource)"/>。</param>
        /// <returns>
        /// 返回一个 <see cref="NDF.ComponentModel.PagingData(TSource)"/>：
        /// 其 Data 属性表示的页面数据内容为源序列 source 的子集，其 PageSize 属性为 <seealso cref="DataPager.DefaultPageSize"/> 属性值，
        /// 其 PageIndex 属性为 0(表示第一页)，其 RowCount 属性为源序列 source 的总元素数量。
        /// </returns>
        public static PagingData<TSource> ToPagingData<TSource>(this IEnumerable<TSource> source, Comparison<TSource> sorter)
        {
            return ToPagingData(source, 0, sorter);
        }

        /// <summary>
        /// 以指定的页面索引号、<seealso cref="DataPager.DefaultPageSize"/> 值指示的默认页面尺寸大小和数据排序方式对序列进行分页处理并返回分页后的结果。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <param name="source">一个 System.Collections.Generic.IEnumerable<T>，用于进行分页处理。</param>
        /// <param name="pageIndex">返回数据页所在源序列中的页面索引号，从 0 开始计数。</param>
        /// <param name="sorter">用于排序比较元素时要使用的 <see cref="System.Comparison(TSource)"/>。</param>
        /// <returns>
        /// 返回一个 <see cref="NDF.ComponentModel.PagingData(TSource)"/>：
        /// 其 Data 属性表示的页面数据内容为源序列 source 的子集，其 PageSize 属性为 <seealso cref="DataPager.DefaultPageSize"/> 属性值，
        /// 其 PageIndex 属性为传入的参数 pageIndex，其 RowCount 属性为源序列 source 的总元素数量。
        /// </returns>
        public static PagingData<TSource> ToPagingData<TSource>(this IEnumerable<TSource> source, int pageIndex, Comparison<TSource> sorter)
        {
            return ToPagingData(source, pageIndex, DataPager.DefaultPageSize, sorter);
        }

        /// <summary>
        /// 以指定的页面索引号、页面尺寸大小和数据排序方式对序列进行分页处理并返回分页后的结果。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <param name="source">一个 System.Collections.Generic.IEnumerable<T>，用于进行分页处理。</param>
        /// <param name="pageIndex">返回数据页所在源序列中的页面索引号，从 0 开始计数。</param>
        /// <param name="pageSize">返回数据页的页面尺寸，即一页有多少行数据。</param>
        /// <param name="sorter">用于排序比较元素时要使用的 <see cref="System.Comparison(TSource)"/>。</param>
        /// <returns>
        /// 返回一个 <see cref="NDF.ComponentModel.PagingData(TSource)"/>：
        /// 其 Data 属性表示的页面数据内容为源序列 source 的子集，其 PageSize 属性为传入的参数 pageSize，
        /// 其 PageIndex 属性为传入的参数 pageIndex，其 RowCount 属性为源序列 source 的总元素数量。
        /// </returns>
        public static PagingData<TSource> ToPagingData<TSource>(this IEnumerable<TSource> source, int pageIndex, int pageSize, Comparison<TSource> sorter)
        {
            return new PagingData<TSource>(pageIndex, pageSize, source.Count(), source.SplitPage(pageIndex, pageSize, sorter));
        }




        public static IEnumerable<TSource> Sort<TSource>(this IEnumerable<TSource> source)
        {
            var list = source.ToList();
            list.Sort();
            return list;
        }

        public static IEnumerable<TSource> Sort<TSource>(this IEnumerable<TSource> source, Comparison<TSource> comparison)
        {
            var list = source.ToList();
            list.Sort(comparison);
            return list;
        }

        public static IEnumerable<TSource> Sort<TSource>(this IEnumerable<TSource> source, IComparer<TSource> comparer)
        {
            var list = source.ToList();
            list.Sort(comparer);
            return list;
        }



        public static IEnumerable<TResult> Cast<TSource, TResult>(this IEnumerable<TSource> source, Converter<TSource, TResult> converter)
        {
            return source.Select(item => converter.Invoke(item));
        }




        public static IEnumerable<TSource> Each<TSource>(this IEnumerable<TSource> source, Action<TSource> handler)
        {
            foreach (var item in source)
            {
                handler.Invoke(item);
                yield return item;
            }
        }

        public static IEnumerable<TSource> Each<TSource>(this IEnumerable<TSource> source, Action<TSource, int> handler)
        {
            var array = source.ToArray();
            for (int i = 0; i < array.Length; i++)
            {
                var item = array[i];
                handler.Invoke(item, i);
                yield return item;
            }
        }



        public static IEnumerable<TSource> Each<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> handler)
        {
            foreach (var item in source)
            {
                if (handler.Invoke(item))
                {
                    yield return item;
                }
                else
                {
                    yield break;
                }
            }
        }

        public static IEnumerable<TSource> Each<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> handler)
        {
            var array = source.ToArray();
            for (int i = 0; i < array.Length; i++)
            {
                var item = array[i];
                if (handler.Invoke(item, i))
                {
                    yield return item;
                }
                else
                {
                    yield break;
                }
            }
        }



        /// <summary>
        /// 将序列中的每个元素通过指定的转换函数进行类型转换，并将所有转换的结果投射到一个新序列中。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <typeparam name="TResult">converter 返回的值的类型。</typeparam>
        /// <param name="source">一个值序列，要对该序列调用转换函数。</param>
        /// <param name="converter">应用于每个元素的转换函数。</param>
        /// <returns>一个 <see cref="System.Collections.Generic.IEnumerable(TSource)"/>，其元素为对 source 的每个元素调用转换函数的结果。</returns>
        public static IEnumerable<TResult> Map<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> converter)
        {
            return source.Select(converter);
        }

        /// <summary>
        /// 将序列中的每个元素通过指定的待索引指示的转换函数进行类型转换，并将所有转换的结果投射到一个新序列中。
        /// </summary>
        /// <typeparam name="TSource">source 中的元素的类型。</typeparam>
        /// <typeparam name="TResult">converter 返回的值的类型。</typeparam>
        /// <param name="source">一个值序列，要对该序列调用转换函数。</param>
        /// <param name="converter">一个应用于每个源元素的转换函数；函数的第二个参数表示源元素的索引。</param>
        /// <returns>一个 <see cref="System.Collections.Generic.IEnumerable(TSource)"/>，其元素为对 source 的每个元素调用转换函数的结果。</returns>
        public static IEnumerable<TResult> Map<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, TResult> converter)
        {
            return source.Select(converter);
        }




        public static IEnumerable<TSource> Remove<TSource>(this IEnumerable<TSource> source, TSource item)
        {
            var list = source.ToList();
            list.Remove(item);
            return list;
        }

        public static IEnumerable<TSource> RemoveAt<TSource>(this IEnumerable<TSource> source, int index)
        {
            var list = source.ToList();
            list.RemoveAt(index);
            return list;
        }


        public static IEnumerable<TSource> RemoveAll<TSource>(this IEnumerable<TSource> source, Predicate<TSource> match, out int count)
        {
            var list = source.ToList();
            count = list.RemoveAll(match);
            return list;
        }

        public static IEnumerable<TSource> RemoveRange<TSource>(this IEnumerable<TSource> source, int index, int count)
        {
            var list = source.ToList();
            list.RemoveRange(index, count);
            return list;
        }







        public static IEnumerable<TSource> Prepend<TSource>(this IEnumerable<TSource> source, TSource item)
        {
            yield return item;
            foreach (var unit in source)
            {
                yield return unit;
            }
        }


        public static IEnumerable<TSource> Append<TSource>(this IEnumerable<TSource> source, TSource item)
        {
            foreach (var unit in source)
            {
                yield return unit;
            }
            yield return item;
        }



        /// <summary>
        /// 将一个二维序列中每个序列的每个元素提取出来，重新构建成一个新的序列并返回。
        /// </summary>
        /// <typeparam name="T">source 中的元素的类型。</typeparam>
        /// <param name="source">一个要投影的值序列。</param>
        /// <returns>一个 <see cref="System.Collections.Generic.IEnumerable(T)"/>，其元素是 source 中的每个序列元素。</returns>
        public static IEnumerable<T> Flatten<T>(this IEnumerable<IEnumerable<T>> source)
        {
            return source.SelectMany(e => e);
        }



        public static IEnumerable<T> Attach<T>(this IEnumerable<T> source, T item)
        {
            return source.Attach(item, EqualityComparer<T>.Default);
        }

        public static IEnumerable<T> Attach<T>(this IEnumerable<T> source, T item, IEqualityComparer<T> comparer)
        {
            return source.Contains(item, comparer) ? source : source.Append(item);
        }
    }
}


namespace NDF.Collections.Generic
{
    /// <summary>
    /// 为常见的快速构建或封装泛型序列 <see cref="System.Collections.Generic.IEnumerable(T)"/> 对象操作提供实用工具方法。
    /// </summary>
    public static class EnumerableHelper
    {
        /// <summary>
        /// 将对象构建成一个泛型序列 <see cref="System.Collections.Generic.IEnumerable(T)"/> 并返回。
        /// </summary>
        /// <typeparam name="T">待返回序列的元素项类型。</typeparam>
        /// <param name="item">待返回序列中包含的元素</param>
        /// <returns>返回一个新创建的序列，该序列中包含一个元素即是 item。</returns>
        public static IEnumerable<T> ToEnumerable<T>(this T item)
        {
            yield return item;
        }
    }
}
